package com.xiyu.service.service.material;

import com.xiyu.service.vo.material.materialInfo.MaterialInfoUpdateInput;
import com.xiyu.service.vo.material.materialInfo.MaterialInfoCreateInput;
import com.xiyu.service.vo.material.materialInfo.MaterialInfoSingleGetOutput;
import com.xiyu.service.model.material.info.MaterialInfo;
import com.xiyu.service.repository.material.info.MaterialInfoRepository;
import com.xiyu.service.vo.material.materialInfo.MaterialInfoPageQueryOutput;
import com.xiyu.service.vo.material.materialInfo.MaterialInfoPageQueryInput;
import com.xiyu.service.vo.material.materialInfo.MaterialInfoSingleGetCategoryOutput;
import com.xiyu.service.vo.material.materialInfo.MaterialInfoUpdateCategoryInput;
import com.xiyu.service.vo.material.materialInfo.MaterialInfoCreateCategoryInput;
import com.xiyu.service.model.material.info.MaterialCategory;
import com.xiyu.service.repository.material.info.MaterialCategoryRepository;
import com.xiyu.service.vo.material.materialInfo.MaterialInfoListQueryCategoryOutput;
import com.xiyu.service.vo.material.materialInfo.MaterialInfoListQueryCategoryInput;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.material.MaterialInfoConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.material.MaterialInfoErrorCode.*;

/**
 * 物资信息 Service 实现类
 */
@Service
@Validated
public class MaterialInfoServiceImpl implements MaterialInfoService {

    @Resource
    private MaterialInfoRepository materialInfoRepository;

    @Resource
    private MaterialCategoryRepository materialCategoryRepository;


    @Override
    public List<MaterialInfoListQueryCategoryOutput> listQueryCategory(MaterialInfoListQueryCategoryInput inputVO) {
        List<MaterialCategory> listMaterialCategory = materialCategoryRepository.listQueryCategory(inputVO);
        return MaterialInfoConvert.INSTANCE.listQueryCategoryOutputConvert(listMaterialCategory);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createCategory(MaterialInfoCreateCategoryInput inputVO) {
        Optional<MaterialCategory> optionalDuplicateMaterialCategory = materialCategoryRepository.findFirstByCategoryName(inputVO.getCategoryName());
        if(optionalDuplicateMaterialCategory.isPresent()){
            throw exception(MATERIAL_CATEGORY_NAME_DUPLICATE);
        }
        MaterialCategory newMaterialCategory = MaterialInfoConvert.INSTANCE.createCategoryInputConvert(inputVO);
        newMaterialCategory = materialCategoryRepository.insert(newMaterialCategory);
        return newMaterialCategory.id();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateCategory(MaterialInfoUpdateCategoryInput inputVO) {
        Optional<MaterialCategory> optionalDuplicateMaterialCategory = materialCategoryRepository.findFirstByCategoryName(inputVO.getCategoryName());
        if(optionalDuplicateMaterialCategory.isPresent() && !inputVO.getId().equals(optionalDuplicateMaterialCategory.get().id())){
            throw exception(MATERIAL_CATEGORY_NAME_DUPLICATE);
        }
        Optional<MaterialCategory> optionalOldMaterialCategory = materialCategoryRepository.findById(inputVO.getId());
        if(!optionalOldMaterialCategory.isPresent()){
            throw exception(MATERIAL_CATEGORY_NOT_EXIST);
        }
        MaterialCategory updateMaterialCategory = MaterialInfoConvert.INSTANCE.updateCategoryInputConvert(inputVO);
        materialCategoryRepository.update(updateMaterialCategory);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deletedCategory(Long id) {
        return null;
    }

    @Override
    public MaterialInfoSingleGetCategoryOutput singleGetCategory(Long id) {
        Optional<MaterialCategory> optionMaterialCategory = materialCategoryRepository.findById(id);
        if(!optionMaterialCategory.isPresent()){
            throw exception(MATERIAL_CATEGORY_NOT_EXIST);
        }
        return MaterialInfoConvert.INSTANCE.singleGetCategoryOutputConvert(optionMaterialCategory.get());

    }

    @Override
    public PageResult<MaterialInfoPageQueryOutput> pageQuery(MaterialInfoPageQueryInput inputVO) {
        Page<MaterialInfo> pageMaterialInfo = materialInfoRepository.pageQuery(inputVO);
        List<MaterialInfoPageQueryOutput> listMaterialInfo = MaterialInfoConvert.INSTANCE.pageQueryOutputConvert(pageMaterialInfo.getRows());
        return new PageResult<>(listMaterialInfo, pageMaterialInfo.getTotalRowCount());
    }

    @Override
    public MaterialInfoSingleGetOutput singleGet(Long id) {
        Optional<MaterialInfo> optionMaterialInfo = materialInfoRepository.findById(id);
        if(!optionMaterialInfo.isPresent()){
            throw exception(MATERIAL_INFO_NOT_EXIST);
        }
        return MaterialInfoConvert.INSTANCE.singleGetOutputConvert(optionMaterialInfo.get());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(MaterialInfoCreateInput inputVO) {
        Optional<MaterialInfo> optionalDuplicateMaterialInfo = materialInfoRepository.findFirstByMaterialName(inputVO.getMaterialName());
        if(optionalDuplicateMaterialInfo.isPresent()){
            throw exception(MATERIAL_INFO_NAME_DUPLICATE);
        }
        MaterialInfo newMaterialInfo = MaterialInfoConvert.INSTANCE.createInputConvert(inputVO);
        newMaterialInfo = materialInfoRepository.insert(newMaterialInfo);
        return newMaterialInfo.id();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(MaterialInfoUpdateInput inputVO) {
        Optional<MaterialInfo> optionalDuplicateMaterialInfo = materialInfoRepository.findFirstByMaterialName(inputVO.getMaterialName());
        if(optionalDuplicateMaterialInfo.isPresent() && !inputVO.getId().equals(optionalDuplicateMaterialInfo.get().id())){
            throw exception(MATERIAL_INFO_NAME_DUPLICATE);
        }
        Optional<MaterialInfo> optionalOldMaterialInfo = materialInfoRepository.findById(inputVO.getId());
        if(!optionalOldMaterialInfo.isPresent()){
            throw exception(MATERIAL_INFO_NOT_EXIST);
        }
        MaterialInfo updateMaterialInfo = MaterialInfoConvert.INSTANCE.updateInputConvert(inputVO);
        materialInfoRepository.update(updateMaterialInfo);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleted(Long id) {
        Optional<MaterialInfo> optionalDeleteMaterialInfo = materialInfoRepository.findById(id);
        if(!optionalDeleteMaterialInfo.isPresent()){
            throw exception(MATERIAL_INFO_NOT_EXIST);
        }
        materialInfoRepository.deleteById(id);
        return true;
    }

}
